package com.example.lib.muchthread;

/**
 * 线程间通讯：
 * 其实就是多个线程在操作同一个资源。
 * 但是操作的动作不同。
 * <p>
 * 等待唤醒机制
 *
 * wait(),notify(),notifyAll();
 * 都使用在同步中，因为要对持有监视器(锁)的线程操作。所以要使用在同步中，因为只有同步才具有锁。
 * 为什么这些操作线程的方法要定义在Object类中呢？
 * 因为这些方法在操作同步线程时，都必须要标识它们所操作线程持有的锁。
 * 只有同一个锁上的被等待线程，可以被同一个锁上notify唤醒。
 * 不可以对不同锁中的线程进行唤醒。
 *
 * 如果同一个锁上有多个被等待线程，notify唤醒的是最先wait的那个线程。
 *
 * 也就是说，等待和唤醒必须是同一个锁。
 *
 * 而锁可以是任意对象，所以可以被任意对象调用的方法定义Object类中。
 *
 *
 */
class Res142 {
    String name;
    String sex;
    boolean flag = false;
}

class Input142 implements Runnable {

    private Res142 res;

    public Input142(Res142 res) {
        this.res = res;
    }

    @Override
    public void run() {
        int x = 0;
        while (true) {
            synchronized (res) {
                if (res.flag){
                    try {
                        res.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (x == 0) {
                    res.name = "mike";
                    res.sex = "man";
                } else {
                    res.name = "丽丽";
                    res.sex = "女";
                }
                x = (x + 1) % 2;
                res.flag=true;
                res.notify();
            }
        }

    }
}

class Output142 implements Runnable {

    private Res142 res;

    public Output142(Res142 res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (res) {
                if (!res.flag){
                    try {
                        res.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.println(res.name + "..." + res.sex);
                res.flag=false;
                res.notify();
            }
        }
    }
}


public class n_thread_conn_142_144 {

    public static void main(String[] args) {
        Res142 res = new Res142();
        Input142 input = new Input142(res);
        Output142 output = new Output142(res);

        Thread t1 = new Thread(input);
        Thread t2 = new Thread(output);

        t1.start();
        t2.start();
    }

}


